package cn.icanci.loopstack.rec.engine.script.client;

import java.util.concurrent.*;

/**
 * 自动重试客户端
 *
 * @author icanci
 * @since 1.0 Created in 2022/11/14 22:16
 */
public abstract class AbstractRetryClient implements Client {

    protected static final ThreadPoolExecutor HTTP_POOL = new ThreadPoolExecutor(40, //
        120, //
        60L, //
        TimeUnit.SECONDS, //
        new LinkedBlockingQueue<>(2000), //
        runnable -> new Thread(runnable, "AbstractRetryClient Pool-" + runnable.hashCode()), //
        (r, executor) -> {
            throw new RuntimeException("AbstractRetryClient Pool is EXHAUSTED!");
        });

    @Override
    public <V> V call(RpcRequest request, Class<V> clazz) throws RemoteException {
        return retry(request, clazz, 0, request.getRetry());
    }

    private <V> V retry(RpcRequest request, Class<V> clazz, int retryCount, int retry) throws RemoteException {
        try {
            return doExecute(request, clazz);
        } catch (RemoteException | ExecutionException | InterruptedException e) {
            throw new RemoteException(e);
        } catch (TimeoutException e) {
            while (retryCount < retry) {
                retryCount++;
                return retry(request, clazz, retryCount, retry);
            }
            throw new RemoteException(e.getMessage(), e);
        }
    }

    protected abstract <V> V doExecute(RpcRequest request, Class<V> clazz) throws ExecutionException, InterruptedException, TimeoutException;

}
